package op_list

import (
	"file_explorer/common/log"
	"file_explorer/common/util"
	"file_explorer/model"
	"file_explorer/service/eventbus"
	"file_explorer/view/packed_widgets"
	"file_explorer/view/store"

	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/container"
	"fyne.io/fyne/v2/theme"
	"fyne.io/fyne/v2/widget"
)

type OpList struct {
	Container *fyne.Container

	deleteButton *packed_widgets.Button
	renameButton *packed_widgets.Button

	opFileList *packed_widgets.Table

	ctx *store.OpListContext
}

// 从context回写CheckList状态
func (opList *OpList) reloadCheckList() {
	if len(opList.ctx.CheckedList) == 0 {
		return
	}
	checkItemSet := make(map[*model.FileInfo]struct{})
	for _, checkItem := range opList.ctx.CheckedList {
		checkItemSet[checkItem] = struct{}{}
	}
	checkIndexList := make([]int, 0, len(checkItemSet))
	for i, fileInfo := range opList.ctx.FileInfos {
		if _, ok := checkItemSet[fileInfo]; ok {
			checkIndexList = append(checkIndexList, i)
		}
	}
	opList.opFileList.Checklist.SetCheckIndexList(checkIndexList)
}

func (opList *OpList) refreshData() {
	if len(opList.ctx.CheckedList) > 0 {
		opList.getDeleteButton().Enable()
		opList.getRenameButton().Enable()
	} else {
		opList.getDeleteButton().Disable()
		opList.getRenameButton().Disable()
	}
}

func (opList *OpList) getDeleteButton() *packed_widgets.Button {
	if opList.deleteButton == nil {
		opList.deleteButton = packed_widgets.NewButton("移除", theme.DeleteIcon(), func() {
			// 将选中文件从操作列表内移除
			checkItemSet := make(map[*model.FileInfo]struct{})
			for _, checkItem := range opList.ctx.CheckedList {
				checkItemSet[checkItem] = struct{}{}
			}
			newFileInfos := make([]*model.FileInfo, 0, len(opList.ctx.FileInfos))
			for _, fileInfo := range opList.ctx.FileInfos {
				if _, ok := checkItemSet[fileInfo]; !ok {
					newFileInfos = append(newFileInfos, fileInfo)
				}
			}

			log.Info("操作列表移除%d项", len(opList.ctx.FileInfos))

			opList.ctx.SetFileInfos(newFileInfos)

			// 清空选中项目
			opList.ctx.CheckedList = nil
			opList.opFileList.Reset()
			opList.ctx.ProduceEvent(eventbus.EventKeyOpListCtxChecklistChange, nil)
		})

		if len(opList.ctx.CheckedList) == 0 {
			opList.deleteButton.Disable()
		}
	}
	return opList.deleteButton
}

func (opList *OpList) getRenameButton() *packed_widgets.Button {
	if opList.renameButton == nil {
		opList.renameButton = packed_widgets.NewButton("重命名", theme.MenuIcon(), func() {
			log.Info("打开重命名页")
			gCtx := opList.ctx.GetGlobalContext()
			gCtx.AddTab(store.NewRenameTabContext(opList.ctx))
		})

		if len(opList.ctx.CheckedList) == 0 {
			opList.renameButton.Disable()
		}
	}
	return opList.renameButton
}

func NewOpList(ctx *store.OpListContext) *OpList {
	opList := &OpList{
		ctx:        ctx,
		opFileList: packed_widgets.NewTable(),
	}

	opList.opFileList.SetGetData(func(index int) interface{} {
		return opList.ctx.FileInfos[index]
	})
	opList.opFileList.SetGetDataLength(func() int {
		return len(opList.ctx.FileInfos)
	})
	opList.opFileList.AddColumn(
		packed_widgets.NewTableColumn().
			SetHeader("名称").
			SetWidth(200).
			SetTextGetter(func(data interface{}) string { return data.(*model.FileInfo).Name }).
			SetOrderBy(func(asc bool) {
				opList.ctx.SetSortFunc(
					util.GetComparatorByPriority[*model.FileInfo](
						asc,
						func(a, b *model.FileInfo) int {
							return int(b.Type) - int(a.Type)
						},
						func(a, b *model.FileInfo) int {
							return util.CmpText(a.Name, b.Name)
						},
					),
				)
			}).
			SetDefaultOrder().
			SetDoubleTappedExpand(),
	)
	opList.opFileList.Build()

	// 排序时同步checklist
	opList.opFileList.RegisterConsumer(eventbus.EventKeyWidgetTableOrderChange, func(event *model.Event) {
		log.Info("操作列表排序变更")
		opList.reloadCheckList()
	})

	// table选中项更新时，同步到ctx
	opList.opFileList.Checklist.RegisterConsumer(eventbus.EventKeyWidgetChecklistChange, func(event *model.Event) {
		log.Info("操作列表选中项变更")
		checkIndexList := opList.opFileList.Checklist.GetCheckIndexList()
		checkList := make([]*model.FileInfo, len(checkIndexList))
		for i, checkIndex := range checkIndexList {
			checkList[i] = opList.ctx.FileInfos[checkIndex]
		}
		opList.ctx.CheckedList = checkList
		opList.ctx.ProduceEvent(eventbus.EventKeyOpListCtxChecklistChange, nil)
		opList.refreshData()
	})

	// 文件列表更新时，同步到table
	opList.ctx.RegisterConsumer(eventbus.EventKeyOpListCtxFileChange, func(event *model.Event) {
		log.Info("操作列表项目变更")
		opList.opFileList.Reset()
		opList.reloadCheckList()
	})

	opList.Container = container.NewBorder(
		container.NewVBox(
			widget.NewToolbar(opList.getDeleteButton(), opList.getRenameButton()),
			widget.NewToolbar(opList.opFileList.Checklist.GetReverseButton(), opList.opFileList.Checklist.GetRangeButton()),
		),
		nil, nil, nil,
		opList.opFileList)

	return opList
}
